// encoding=utf-8

#include <qapplication.h>
#include <qfont.h>
#include <qtextcodec.h>
#include <qdebug.h>
#include <qtabwidget.h>
#include <qtoolbar.h>
#include <qaction.h>
#include <qmenu.h>
#include <qfiledialog.h>
#include <qfileinfo.h>
#include <qmetaobject.h>
#include <qmessagebox.h>
#include <qstatusbar.h>
#include <qlabel.h>
#include <Qsci/qscilexercpp.h>

#include "QyEasyEdit.h"
#include "QySciEdit.h"

/**************************************************************************************************/

inline void setLexerStyle( QsciLexer * lexer, int style, const QColor & fore, const QColor & back,
	const QFont & font, bool eol=false )
{

	lexer->setColor( fore, style );
	lexer->setPaper( back, style );
	lexer->setFont( font, style );
	lexer->setEolFill( eol, style );

}

inline void setGlobalLexerFont( QsciLexer * lexer, int count, const QFont & font ) {

	for ( int i=0; i<count; i++ )
		lexer->setFont(font);

}

inline QsciLexer * createCppLexer( QsciScintilla * scintilla ) {

	static QFont nfont( "terminus", 12 ),
		bfont( "terminus", 12, QFont::Bold );
	static QColor bgColor("#181818"),
		cmColor("#5F5F5F");
	QsciLexerCPP * cppLexer = new QsciLexerCPP(scintilla);

	cppLexer->setFoldComments(true);
	cppLexer->setFoldAtElse(true);
	cppLexer->setFoldCompact(false);
	cppLexer->setDefaultPaper(bgColor);
	cppLexer->setDefaultColor("#5F5F5F");

	// setGlobalLexerFont( cppLexer, QsciLexerCPP::GlobalClass, nfont );

	::setLexerStyle( cppLexer, QsciLexerCPP::Default, 				"#af5f24", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::Comment, 				"#5f5f5f", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::CommentLine, 			"#5f5f5f", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::CommentDoc, 			"#5f5f5f", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::Number, 				"#ff9c00", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::Keyword, 				"#AF5F24", bgColor, bfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::DoubleQuotedString, 	"#ff9C00", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::SingleQuotedString, 	"#ff9C00", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::UUID, 					"#ff0000", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::PreProcessor, 			"#f0f0f0", cmColor, nfont, true );
	::setLexerStyle( cppLexer, QsciLexerCPP::Operator, 				"#af5f24", bgColor, bfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::Identifier, 			"#c3c3c3", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::UnclosedString, 		"#ffffff","#ff0000",nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::VerbatimString, 		"#00ff00", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::Regex, 				"#ff9C00", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::CommentLineDoc, 		"#ff0000", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::KeywordSet2, 			"#ff9c00", bgColor, bfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::CommentDocKeyword, 	"#5f5f5f", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::CommentDocKeywordError,"#5f5f5f", bgColor, nfont );
	::setLexerStyle( cppLexer, QsciLexerCPP::GlobalClass, 			"#af5f24", bgColor, bfont );

	scintilla->setCallTipsBackgroundColor("#ff0000");
	scintilla->setCallTipsForegroundColor("#c3c3c3");
	scintilla->setCallTipsHighlightColor("#af5f24");
	scintilla->setPaper(bgColor);
	scintilla->setColor("#5F5F5F");
	scintilla->setMarginsBackgroundColor(bgColor);
	scintilla->setMarginsForegroundColor("#ffffff");
	scintilla->setFoldMarginColors( "#af5f24", "#af5f24");
	scintilla->setCaretForegroundColor("#ff0000");
	scintilla->setCaretLineBackgroundColor("#000000");
	scintilla->setIndentationGuidesBackgroundColor("#ff9C00");
	scintilla->setIndentationGuidesForegroundColor("#ff9C00");
	scintilla->setSelectionForegroundColor("#f0f0f0");
	scintilla->setSelectionBackgroundColor("#af5f24");
	scintilla->setMatchedBraceBackgroundColor(bgColor);
	scintilla->setMatchedBraceForegroundColor("#ff9C00");
	scintilla->setUnmatchedBraceBackgroundColor(bgColor);
	scintilla->setUnmatchedBraceForegroundColor("#ff0000");
	scintilla->setEdgeColor("#ff0000");

	return cppLexer;
}

inline QAction * createAction( QObject * parent, const QString & name, const QString & text,
	const QString & key=QString(), const QPixmap & pixmap=QPixmap() )
{

	QAction * action = new QAction( pixmap, text, parent );

	action->setObjectName(name);
	action->setShortcut( QKeySequence(key) );

	return action;
}

/**************************************************************************************************/

QyEasyEdit::QyEasyEdit() : QMainWindow() {

	tabWidget = new QTabWidget(this);
	encodingStatus = new QLabel( "<e>", this );
	QStatusBar * statusBar = new QStatusBar(this);

	tabWidget->setObjectName("tabWidget");
	statusBar->addWidget(encodingStatus);
	createMenu();
	setStatusBar(statusBar);
	setCentralWidget(tabWidget);
	QMetaObject::connectSlotsByName(this);
	on_newTabAction_triggered();

}

QyEasyEdit::~QyEasyEdit() {
}

void QyEasyEdit::openFile( const QString & fileName ) {

	QySciEdit * edit = 0;

	if ( QFile::exists(fileName) )
		tabWidget->addTab( edit = new QySciEdit( fileName, tabWidget ), QFileInfo(fileName).fileName() );
	else
		tabWidget->addTab( edit = new QySciEdit(tabWidget), tr("new tab") );

	tabWidget->setCurrentWidget(edit);

	connect( edit, SIGNAL( encodingChanged(const QString&) ),
		this, SLOT( encodingChanged(const QString&) ) );
	connect( edit, SIGNAL( fileNameChanged(const QString&) ),
		this, SLOT( fileNameChanged(const QString&) ) );
	connect( edit, SIGNAL( linesChanged() ),
		this, SLOT( linesChanged() ) );
	connect( edit, SIGNAL( cursorPositionChanged(int,int) ),
		this, SLOT( cursorPositionChanged(int,int) ) );

}

void QyEasyEdit::on_newTabAction_triggered() {

	openFile();

}

void QyEasyEdit::on_openAction_triggered() {

	QString fileName( QFileDialog::getOpenFileName(this) );

	if ( fileName.isEmpty() )
		return;

	openFile(fileName);

}

void QyEasyEdit::on_saveAction_triggered() {

	QySciEdit * edit = dynamic_cast<QySciEdit*>( tabWidget->currentWidget() );

	if (!edit)
		return;

	QString fileName( edit->fileName() );

	if ( fileName.isEmpty() )
		fileName = QFileDialog::getSaveFileName(this);

	if ( fileName.isEmpty() )
		return;

	if ( fileName != edit->fileName() ) {

		if ( QMessageBox::question( this, tr("Saving ..."), tr("File already exists. Overwrite?"),
				QMessageBox::Save|QMessageBox::Cancel
			) == QMessageBox::Cancel )
		{
			return;
		}

	}

	edit->save(fileName);

}

void QyEasyEdit::on_closeTabAction_triggered() {

	QySciEdit * edit = dynamic_cast<QySciEdit*>( tabWidget->currentWidget() );

	if (edit)
		delete edit;

	if ( !tabWidget->count() )
		openFile();

}

void QyEasyEdit::encodingChanged( const QString & ) {

	updateStatusBar();

}

void QyEasyEdit::fileNameChanged( const QString & ) {

	updateStatusBar();

}

void QyEasyEdit::on_tabWidget_currentChanged( int ) {

	updateStatusBar();

}

void QyEasyEdit::linesChanged() {

	updateStatusBar();

}

void QyEasyEdit::cursorPositionChanged( int, int ) {

	updateStatusBar();

}

void QyEasyEdit::createMenu() {

	QToolBar * fileToolBar = addToolBar( tr("File") );

	fileToolBar->addAction( createAction( this, "newTabAction", tr("New tab"), "Ctrl+T" ) );
	fileToolBar->addAction( createAction( this, "openAction", tr("Open"), "Ctrl+O" ) );
	fileToolBar->addAction( createAction( this, "saveAction", tr("Save"), "Ctrl+S" ) );
	fileToolBar->addAction( createAction( this, "closeTabAction", tr("Close tab"), "Ctrl+W" ) );

}

void QyEasyEdit::updateStatusBar() {

	QySciEdit * edit = dynamic_cast<QySciEdit*>( tabWidget->currentWidget() );

	if (edit)
		encodingStatus->setText( QString("Encoding: %1, Line: %2/%3, Pos: %4/%5")
			.arg( edit->encodingName() )
			.arg( edit->line() + 1 ).arg( edit->lines() )
			.arg( edit->index() ).arg( edit->trueLineLength( edit->line() ) )
		);
	else
		encodingStatus->setText( "" );

}

/**************************************************************************************************/

int main( int argc, char ** argv ) {

	QApplication app( argc, argv );
	// QTextCodec * codec = QTextCodec::codecForName("System");

	app.setFont( QFont( "terminus", 10 ) );

	QyEasyEdit mainWindow;
	mainWindow.show();
	mainWindow.move( 300, 300 );
	mainWindow.resize( 640, 480 );
	// QySciEdit edit;

	// /*edit.setText( codec->toUnicode(
		// "#include <qapplication.h>\n"
		// "#include <qfont.h>\n"
		// "\n"
		// "#include \"QySciEdit.h\"\n"
		// "\n"
		// "int main( int argc, char ** argv ) {\n"
		// "\n"
		// "	QApplication app( argc, argv );\n"
		// "\n"
		// "	app.setFont( QFont( \"terminus\", 10 ) );\n"
		// "\n"
		// "	QySciEdit edit;\n"
		// "\n"
		// "	edit.show();\n"
		// "	Это отечественные букафки =)\n"
		// "	return app.exec();\n"
		// "}\n"
	// ) );*/
	// edit.setLexer( createCppLexer(&edit) );
	// edit.show();
	// edit.move( 300, 300 );
	// edit.resize( 640, 480 );
	// edit.setFocus();
	// edit.marginArrow().setPosition(1);

	return app.exec();
}
